package com.rslai.base.tool.servertest.casefilter;

import com.rslai.base.tool.servertest.model.TestCase;
import com.rslai.base.tool.servertest.model.TestSuite;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;

public class TagFilter implements CaseFilter {
    private List<String> expectedTags;

    public TagFilter(List<String> expectedTags) {
        this.expectedTags = expectedTags;
    }

    public void filter(TestSuite testSuite) {
        if (matchAllTags()) return;
        if (ignoreTestSuitTags(testSuite)) {
            List testCases = testSuite.getTestCases();
            testSuite.setTestCases(filterCaseByTags(testCases, false));
            return;
        }

        if (!tagCanBeMatch(testSuite.getTags(), true)) {
            testSuite.setTestCases(new ArrayList(0));
        } else {
            List testCases = testSuite.getTestCases();
            List runableCases = new ArrayList();
            runableCases.addAll(filterCaseByTags(testCases, true));
            runableCases.addAll(withoutTags(testCases));
            testSuite.setTestCases(new ArrayList(new LinkedHashSet(runableCases)));
        }
    }

    private boolean matchAllTags() {
        return this.expectedTags.contains("*");
    }

    private List<TestCase> withoutTags(List<TestCase> testCases) {
        List result = new ArrayList();
        for (TestCase testCase : testCases) {
            if ((testCase.getTag() == null) || (testCase.getTag().size() == 0)) {
                result.add(testCase);
            }
        }
        return result;
    }

    private boolean ignoreTestSuitTags(TestSuite testSuite) {
        List tags = testSuite.getTags();
        return (tags == null) || (tags.size() == 0);
    }

    private List<TestCase> filterCaseByTags(List<TestCase> testCases, boolean suiteHasTags) {
        List list = new ArrayList();
        for (TestCase testCase : testCases) {
            if (tagCanBeMatch(testCase.getTag(), suiteHasTags)) {
                list.add(testCase);
            }
        }
        return list;
    }

    private boolean tagCanBeMatch(List<String> actualTags, boolean suiteHasTags) {
        if (((actualTags == null) || (actualTags.size() == 0)) && (suiteHasTags)) {
            return true;
        }
        TagExpression expression = new TagExpression(this.expectedTags);
        return expression.eval(actualTags);
    }
}
